#include <iostream>
#include <string.h>
#define WORD uint16_t
#define DWORD uint32_t
#define QWORD uint64_t
#define HIWORD(I) ( ( WORD ) ( ( ( DWORD )( I ) >> 16) & 0xFFFF ) )
#define HIDWORD(I) ( ( DWORD ) ( ( ( QWORD )( I ) >> 32) & 0xFFFFFFFF ) )

uint32_t g_uid_map4[4] = {0xCBF6CFF8, 0x97ED9FF0, 0x63E46FE8, 0x2FDB3FE0};
uint32_t g_uid_map3 = 0xCBF6CFF7; // 1100 1011 1111 0110 1100 1111 1111 0111
uint32_t g_uid_map2 = 0x7ed9fee0; //       011 1111 0110 1100 1111 1111 0111 0000 0
uint32_t g_uid_map = 0xCBF65;
uint32_t g_uid = 835429;

// sub_1400026E0的逆推算法
uint reverse_sub_1400026E0(unsigned int *flag_enc_slice, const uint32_t *uid_map4, unsigned int uid_map3, unsigned int uid_map2){
    unsigned int slice_0 = flag_enc_slice[0];
    unsigned int slice_1 = flag_enc_slice[1];
    uid_map2 = 0;
    for(int i=0;i < 0x20;i++){
        uid_map2 += uid_map3;
        slice_0 += (uid_map4[1] + (slice_1 >> 5)) ^ (uid_map2 + slice_1) ^ (uid_map4[0] + 16 * slice_1);
        slice_1 += (uid_map4[3] + (slice_0 >> 5)) ^ (uid_map2 + slice_0) ^ (uid_map4[2] + 16 * slice_0);
    }
    flag_enc_slice[0] = slice_0;
    flag_enc_slice[1] = slice_1;
    return uid_map2;
}


// 用于处理flag_enc的函数，flag_enc 被处理后内容应当等于 "flag{!!!_HAPPY_NEW_YEAR_2023!!!}"
// 逆推得到 flag_enc 的内容为
/*
   70 7b 7a e9   16 3c 7d 05   92 d5 a6 ba   18 56 37 a7
   02 06 40 1c   0b 8a 0f ec   45 49 3e b3   7b d2 35 04
 */
// 据此求得一个可行解为 e97a7b7__57d3c16baa6d592a73756181c4__6_2ec_f8a_bb33e4945_435d27b，其中_可以用不表示十六进制的任意ASCII字符代替
uint sub_1400026E0(unsigned int *flag_enc_slice, const uint32_t *uid_map4, unsigned int uid_map3, unsigned int uid_map2)
{
    unsigned int slice_0; // [rsp+0h] [rbp-28h]
    unsigned int slice_1; // [rsp+4h] [rbp-24h]

    slice_0 = flag_enc_slice[0];
    slice_1 = flag_enc_slice[1];
    for (int i = 0; i < 0x20; ++i )
    {
//        slice_1 -= (uid_map4[3] + (slice_0 >> 5)) ^ (uid_map2 + slice_0) ^ (uid_map4[2] + 16 * slice_0);
        slice_1 -= (uid_map4[3] + (slice_0 >> 5)) ^ (uid_map2 + slice_0) ^ (uid_map4[2] + 16 * slice_0);
        slice_0 -= (uid_map4[1] + (slice_1 >> 5)) ^ (uid_map2 + slice_1) ^ (uid_map4[0] + 16 * slice_1);
        uid_map2 -= uid_map3;
    }
    // flag{!!!_HAPPY_NEW_YEAR_2023!!!}
    // 在第一轮计算结果中，slice_0 = { 'f','l','a','g' } = { 0x66,0x6C,0x61,0x67}
    flag_enc_slice[0] = slice_0;
    // 在第一轮计算结果中，slice_1 = { '!','!','!','_' } = { 0x21,0x21,0x21,0x5F}
    flag_enc_slice[1] = slice_1;
//    return 0;
    return uid_map2;
}

uint32_t sub_1400024A0(const wchar_t *flag_content_slice)
{
    uint32_t result; // [rsp+24h] [rbp-14h]
    result = 0;
    if ( wcslen(flag_content_slice) != 8 )
        return 0;
    // 将 flag 的每 8 个宽字符压缩到一个整数内，其中仅处理【数字与字母a-f、A-F】，其余内容填充时视为0
    for (int i = 0; i < 8; ++i )
    {
        // 将结果右移四位
//        result *= 16;
        result = result << 4;
        if ('0' <= flag_content_slice[i] && flag_content_slice[i] <= '9' ){ // 48 ~ 57
            // 将数字字符转为二进制形式
            result += flag_content_slice[i] - '0';
        }
        if ('A' <= flag_content_slice[i] && flag_content_slice[i] <= 'F' ){ // 65 ~ 70
            // 处理部分大写字母，被处理的大写字母 -55
            // 处理后的范围在 10~15之间
            result += flag_content_slice[i] - '7';
        }
        if ('a' <= flag_content_slice[i] && flag_content_slice[i] <= 'f' ){ // 97 ~ 102
            // 处理部分小写字母，小写字母 -87
            // 处理后的范围在 10~15 之间
            result += flag_content_slice[i] - 'W';
        }
    }
    return result;
}

int64_t  sub_140002900(wchar_t *flag_content, u_int32_t* flag_enc)
{
    wchar_t v3; // [rsp+20h] [rbp-28h]
    int v4; // [rsp+24h] [rbp-24h]
    unsigned int v5; // [rsp+28h] [rbp-20h]

    v4 = 0;
    v5 = 0;
    while ( flag_content[v4] )
    {
        v3 = flag_content[v4 + 8];
        flag_content[v4 + 8] = 0;
        // *(_DWORD *)(flag_enc + 4 * (int)v5) = sub_1400024A0(&flag_content[v4]);
        flag_enc[v5] = sub_1400024A0(&flag_content[v4]);
        v5++;
        flag_content[v4 + 8] ^= v3;
        v4 += 8;
    }
    return v5;
}


int main() {
//    uint32_t flag_enc[] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
//    printf("%d\n", sub_1400026E0(flag_enc,g_uid_map4,g_uid_map3,g_uid_map2));
//    printf("\n");
    uint32_t flag_len = 64;
    wchar_t* flag = (wchar_t*)calloc(flag_len + 1,sizeof(wchar_t ));
//    memcpy(flag,L"flag{12345678901234567890123456}",32 * sizeof(wchar_t ));
    memcpy(flag,L"FLag{1234567890abCDefghij1234561234567890abCDefghij1234567890ab}",flag_len * sizeof(wchar_t ));
    // flag_enc 是 flag的信息摘要，只有16字节，原始的flag信息长度是64位的
    u_int32_t* flag_enc = (u_int32_t *)calloc(8,sizeof(u_int32_t ));
    // 解算 flag_enc
    sub_140002900(flag, flag_enc);

    printf("%ls\n",flag_enc);
    // 变换flag_enc
    for(int m=0;m<7;m+=2){
        sub_1400026E0( &flag_enc[m] ,g_uid_map4,g_uid_map3,g_uid_map2);
    }
    // 变换后的 flag_enc 应为 flag{!!!_HAPPY_NEW_YEAR_2023!!!}
    // flag_enc 在 ida 中的地址为 014E390
    printf("%ls\n",flag_enc);

    // 逆变换flag_enc
    for(int m=0;m<7;m+=2){
        reverse_sub_1400026E0( &flag_enc[m] ,g_uid_map4,g_uid_map3,g_uid_map2);
    }

    printf("%ls\n",flag_enc);


    /*
     * 以上代码均用于测试算法正确性，实际使用时，请根据笔记的提示用动态调试以此找到自己的 uid_map2, uid_map3, uid_map4，用于替换对应的全局变量
     * 然后用以下代码求出目标flag的逆，用动态调试将对应的16进制取出
        //    u_int32_t* flag_target = (u_int32_t *)calloc(8,sizeof(u_int32_t ));
        //
        //    memcpy(flag_target,"flag{!!!_HAPPY_NEW_YEAR_2023!!!}",32*sizeof(char));
        //    for(int m=0;m<7;m+=2){
        //        reverse_sub_1400026E0( &flag_target[m] ,g_uid_map4,g_uid_map3,g_uid_map2);
        //    }
        //    printf("%ls\n",flag_target);

        我运行这段代码求得的逆为
            70 7b 7a e9   16 3c 7d 05   92 d5 a6 ba   18 56 37 a7
            02 06 40 1c   0b 8a 0f ec   45 49 3e b3   7b d2 35 04
        然后将字节顺序颠倒，写为（实际上flag的长度是64位，且没有包装）
            e97a7b70057d3c16baa6d592a73756181c400602ec0f8a0bb33e49450435d27b
        将这段字符串提交到论坛就行了
     */


}


